package epoverty;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.design.JRDesignQuery;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.view.JasperViewer;

public class Report
{

    /**
     * Test main method. Currently only runs the donorsLastDonation report
     * @param args 
     */
    public static void main( String[] args )
    {
        //donorsLastDonation();
        //fundraiserMonthly();
        //fundraiserWeekly();
        
        Calendar cal = Calendar.getInstance();
        cal.set( Calendar.MONTH, Calendar.FEBRUARY);
        cal.clear( Calendar.HOUR_OF_DAY );
        cal.clear( Calendar.HOUR );
        cal.clear( Calendar.MINUTE );
        cal.clear( Calendar.SECOND );
        cal.clear( Calendar.MILLISECOND );
        Date from = cal.getTime();
        
        cal.set( Calendar.MONTH, Calendar.MAY);
        Date to = cal.getTime();
        //fundraiserBetween( from, to );
        allAccountsBetween( from, to );
        //accountBetween( 2, from, to);
        //donationsBetween( from, to );
        //referrals();
        //donationsMonthly();
        //allDonors( from, to );
        //allFunraisers( from, to );
        
    }
    
    static private final SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );

    //Report to show the last donation for each donor
    public static void donorsLastDonation()
    {
        DoReport( "donorLastDonation.jrxml", null );
    }

    /**
   * Creates current week report for donations
   * Takes the current week and runs the report
   */
    public static void donationsWeekly()
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();

        donationsWeekly(cal);
    }
    
    /**
     * Report for donations using provided week
     * @param week 
     */
    public static void donationsWeekly(Date week)
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();
        cal.setTime( week );

        donationsWeekly(cal);
    }
    
    /**
     * Report for donations using provided week
     * @param week 
     */
    public static void donationsWeekly(Calendar week)
    {
        week.clear( Calendar.HOUR_OF_DAY );
        week.clear( Calendar.HOUR );
        week.clear( Calendar.MINUTE );
        week.clear( Calendar.SECOND );
        week.clear( Calendar.MILLISECOND );
        
        
        //set the calendar to the first of the month
        week.set( Calendar.DAY_OF_WEEK, week.getActualMinimum( Calendar.DAY_OF_WEEK) );
        Date from = week.getTime();
        
        //set the calendar to the end of the month
        week.set( Calendar.DAY_OF_WEEK, week.getActualMaximum( Calendar.DAY_OF_WEEK) );
        Date to = week.getTime();
        
        donationsBetween(from, to);
    }

    
    /**
     * Report for donations using current month
     */
    public static void donationsMonthly()
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();

        donationsMonthly(cal);
    }
    
    
    /**
     * Report for donations using provided month
     * @param month 
     */
    public static void donationsMonthly( Date month )
    {
        Calendar cal = Calendar.getInstance();
        cal.setTime( month );
        
        donationsMonthly(cal);
    }
    
    /**
     * Report for donations using provided month
     * @param month 
     */
    public static void donationsMonthly( Calendar month )
    {
        month.clear( Calendar.HOUR_OF_DAY );
        month.clear( Calendar.HOUR );
        month.clear( Calendar.MINUTE );
        month.clear( Calendar.SECOND );
        month.clear( Calendar.MILLISECOND );
        
        
        //set the calendar to the first of the month
        month.set( Calendar.DAY_OF_MONTH, month.getActualMinimum( Calendar.DAY_OF_MONTH) );
        Date from = month.getTime();
        
        //set the calendar to the end of the month
        month.set( Calendar.DAY_OF_MONTH, month.getActualMaximum( Calendar.DAY_OF_MONTH) );
        Date to = month.getTime();
        
        donationsBetween(from, to);


    }
    
    /**
     * Report for donations between the two dates provided
     * @param from
     * @param to 
     */
    public static void donationsBetween( Date from, Date to )
    {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("fromDate",from );
        param.put("toDate",to );
        DoReport("donations.jrxml", param);
        
    }
    
    /**
     * Report for fundraisers using current week
     */
    public static void fundraiserWeekly()
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();

        fundraiserWeekly(cal);
    }
    
    /**
     * Report for fundraisers using provided week
     * @param week 
     */
    public static void fundraiserWeekly(Date week)
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();
        cal.setTime( week );

        fundraiserWeekly(cal);
    }
    
    /**
     * Report for fundraisers using provided week
     * @param week 
     */
    public static void fundraiserWeekly(Calendar week)
    {
        week.clear( Calendar.HOUR_OF_DAY );
        week.clear( Calendar.HOUR );
        week.clear( Calendar.MINUTE );
        week.clear( Calendar.SECOND );
        week.clear( Calendar.MILLISECOND );
        
        
        //set the calendar to the first of the month
        week.set( Calendar.DAY_OF_WEEK, week.getActualMinimum( Calendar.DAY_OF_WEEK) );
        Date from = week.getTime();
        
        //set the calendar to the end of the month
        week.set( Calendar.DAY_OF_WEEK, week.getActualMaximum( Calendar.DAY_OF_WEEK) );
        Date to = week.getTime();
        
        fundraiserBetween(from, to);
    }

    
    /**
     * Report for fundraisers for current month
     */
    public static void fundraiserMonthly()
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();

        fundraiserMonthly(cal);
    }
    
    /**
     * Report for fundraisers for provided month
     * @param month 
     */
    public static void fundraiserMonthly( Date month )
    {
        Calendar cal = Calendar.getInstance();
        cal.setTime( month );
        
        fundraiserMonthly(cal);
    }
    
    /**
     * Report for fundraisers for provided month
     * @param month 
     */
    public static void fundraiserMonthly( Calendar month )
    {
        month.clear( Calendar.HOUR_OF_DAY );
        month.clear( Calendar.HOUR );
        month.clear( Calendar.MINUTE );
        month.clear( Calendar.SECOND );
        month.clear( Calendar.MILLISECOND );
        
        
        //set the calendar to the first of the month
        month.set( Calendar.DAY_OF_MONTH, month.getActualMinimum( Calendar.DAY_OF_MONTH) );
        Date from = month.getTime();
        
        //set the calendar to the end of the month
        month.set( Calendar.DAY_OF_MONTH, month.getActualMaximum( Calendar.DAY_OF_MONTH) );
        Date to = month.getTime();
        
        fundraiserBetween(from, to);


    }
    
    /**
     * Report for fundraisers between the provided dates
     * @param from
     * @param to 
     */
    public static void fundraiserBetween( Date from, Date to )
    {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("fromDate",from );
        param.put("toDate",to );
        DoReport("fundraisers.jrxml", param);
    }

    /**
     * Report for all accounts using current week
     */
    public static void allAccountsWeekly()
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();

        allAccountsWeekly(cal);
    }
    
    /**
     * Report for all accounts using provided week
     * @param week 
     */
    public static void allAccountsWeekly(Date week)
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();
        cal.setTime( week );

        allAccountsWeekly(cal);
    }
    
    /**
     * Report for all accounts using provided week
     * @param week 
     */
    public static void allAccountsWeekly(Calendar week)
    {
        week.clear( Calendar.HOUR_OF_DAY );
        week.clear( Calendar.HOUR );
        week.clear( Calendar.MINUTE );
        week.clear( Calendar.SECOND );
        week.clear( Calendar.MILLISECOND );
        
        
        //set the calendar to the first of the month
        week.set( Calendar.DAY_OF_WEEK, week.getActualMinimum( Calendar.DAY_OF_WEEK) );
        Date from = week.getTime();
        
        //set the calendar to the end of the month
        week.set( Calendar.DAY_OF_WEEK, week.getActualMaximum( Calendar.DAY_OF_WEEK) );
        Date to = week.getTime();
        
        allAccountsBetween(from, to);
    }

    
    /**
     * Report for all accounts using current month
     */
    public static void allAccountsMonthly()
    {
        // get today and clear time of day
        Calendar cal = Calendar.getInstance();

        allAccountsMonthly(cal);
    }
    
    
    /**
     * Report for all accounts using provided month
     * @param month 
     */
    public static void allAccountsMonthly( Date month )
    {
        Calendar cal = Calendar.getInstance();
        cal.setTime( month );
        
        allAccountsMonthly(cal);
    }
    
    /**
     * Report for all accounts using provided month
     * @param month
     */
    public static void allAccountsMonthly( Calendar month )
    {
        month.clear( Calendar.HOUR_OF_DAY );
        month.clear( Calendar.HOUR );
        month.clear( Calendar.MINUTE );
        month.clear( Calendar.SECOND );
        month.clear( Calendar.MILLISECOND );
        
        
        //set the calendar to the first of the month
        month.set( Calendar.DAY_OF_MONTH, month.getActualMinimum( Calendar.DAY_OF_MONTH) );
        Date from = month.getTime();
        
        //set the calendar to the end of the month
        month.set( Calendar.DAY_OF_MONTH, month.getActualMaximum( Calendar.DAY_OF_MONTH) );
        Date to = month.getTime();
        
        allAccountsBetween(from, to);


    }
    
    /**
     * Report for all accounts between two dates
     * @param from
     * @param to 
     */
    public static void allAccountsBetween( Date from, Date to )
    {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("fromDate",from );
        param.put("toDate",to );
        DoReport( "allAccounts.jrxml", param);
    }
    
    /**
     * Report of all donors between two dates
     * @param from
     * @param to 
     */
    public static void allDonors( Date from, Date to )
    {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("fromDate",from );
        param.put("toDate",to );
        DoReport( "allDonors.jrxml", param);
    }

    /**
     * Report of all fundraisers between two dates
     * @param from
     * @param to 
     */
    public static void allFunraisers( Date from, Date to )
    {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("fromDate",from );
        param.put("toDate",to );
        DoReport( "allFundraisers.jrxml", param);
    }
    /**
     * Generate a list of persons with the persons they've referred
     */
    public static void referrals()
    {
        DoReport( "referrals.jrxml", null);
    }


    /*
     * Report for account using an account type (one of the final integers in the class)
     */
    public static void accountMonthly( int accountId )
    {
        Calendar cal = Calendar.getInstance();
   
        accountMonthly(accountId, cal.getTime());
    }
    
    /*
     * Report for account using an account type (one of the final integers in the class)
     */
    public static void accountMonthly( int accountId, Date month )
    {
        Calendar cal = Calendar.getInstance();
        cal.setTime( month );
        cal.clear( Calendar.HOUR_OF_DAY );
        cal.clear( Calendar.HOUR );
        cal.clear( Calendar.MINUTE );
        cal.clear( Calendar.SECOND );
        cal.clear( Calendar.MILLISECOND );
        
        
        //set the calendar to the first of the month
        cal.set( Calendar.DAY_OF_MONTH, cal.getActualMinimum( Calendar.DAY_OF_MONTH) );
        Date from = cal.getTime();
        
        //set the calendar to the end of the month
        cal.set( Calendar.DAY_OF_MONTH, cal.getActualMaximum( Calendar.DAY_OF_MONTH) );
        Date to = cal.getTime();
        
        accountBetween(accountId, from, to);
    }
    
    /*
     * Report for account using an account type (one of the final integers in the class)
     */
    public static void accountWeekly( int accountId )
    {
        Calendar cal = Calendar.getInstance();
   
        accountWeekly(accountId, cal.getTime());
    }
    
    public static void accountWeekly( int accountId, Date month )
    {
        Calendar cal = Calendar.getInstance();
        cal.setTime( month );
        cal.clear( Calendar.HOUR_OF_DAY );
        cal.clear( Calendar.HOUR );
        cal.clear( Calendar.MINUTE );
        cal.clear( Calendar.SECOND );
        cal.clear( Calendar.MILLISECOND );
        
        
        //set the calendar to the first of the month
        cal.set( Calendar.DAY_OF_MONTH, cal.getActualMinimum( Calendar.DAY_OF_MONTH) );
        Date from = cal.getTime();
        
        //set the calendar to the end of the month
        cal.set( Calendar.DAY_OF_MONTH, cal.getActualMaximum( Calendar.DAY_OF_MONTH) );
        Date to = cal.getTime();
        
        accountBetween(accountId, from, to);
    }
    /**
     * Generates an account using an account type report between two dates.
     * Use one of the final integers in the class
     * @param type
     * @param from
     * @param to 
     */
    public static void accountBetween( int accountId, Date from, Date to )
    {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("fromDate",from );
        param.put("toDate",to );
        param.put("accountId",accountId );
        DoReport( "accounts.jrxml", param);
    }

    private static void DoReport( String file, Map param )
    {

        try {
            
            File theFile = new File( file );
            JasperDesign jasperDesign = JRXmlLoader.load( theFile );

            JasperReport jasperReport = JasperCompileManager.compileReport( jasperDesign );
            Connection conn = DBconnection.getConnection();
            JasperPrint jasperPrint = JasperFillManager.fillReport( jasperReport, param, conn );
            JasperViewer.viewReport( jasperPrint, false );
            
        }
        catch ( Exception ex ) {
            String connectMsg = "Could not create the report " + ex.getMessage() + " " + ex.getLocalizedMessage();
            System.out.println( connectMsg );
        }

    }

}
